package com.biboheart.adapter.adapter.impl;

import com.biboheart.adapter.compiler.CompilerBuilder;
import com.biboheart.adapter.compiler.ast.Node;
import com.biboheart.adapter.support.enums.StructureTypeEnum;
import com.biboheart.adapter.support.exception.ConvertException;
import com.biboheart.adapter.support.utils.JsonUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.Getter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Getter
final class Structure {
    private final StructureNode structureNode;
    //private final List<String> structureNodeNameList = new ArrayList<>();
    //private final Map<String, StructureNode> structureNodeHash = new HashMap<>();

    public Structure(String describe) throws ConvertException {
        structureNode = new StructureNode(describe, null, null);
        //createHash(structureNode);
    }

    /*private void createHash(StructureNode node) {
        if (null == node.getNode() && null == node.getChildren()) {
            return;
        }
        structureNodeHash.put(node.getName(), node);
        structureNodeNameList.add(node.getName());
        List<StructureNode> children = node.getChildren();
        if (children.isEmpty()) {
            return;
        }
        for (StructureNode child : children) {
            createHash(child);
        }
    }*/

    // 结构的一个节点
    @Getter
    public static class StructureNode {
        private final String name;
        private final String parentName;
        private StructureTypeEnum type;
        private Node node;
        private final List<StructureNode> children = new ArrayList<>();

        private StructureNode(Object obj, String name, String parentName) throws ConvertException {
            this.name = null == name ? "" : name;
            this.parentName = null == parentName ? "" : parentName;
            analysis(obj, null);
        }

        @SuppressWarnings("unchecked")
        private void analysis(Object obj, StructureTypeEnum structureType) throws ConvertException {
            if (null == obj) {
                return;
            }
            List<Object> list = null;
            Map<String, Object> map = null;
            if (obj instanceof String) {
                String describe = String.valueOf(obj);
                if (describe.isEmpty()) {
                    return;
                }
                char first = describe.charAt(0);
                if ('[' != first && '{' != first) {
                    type = null != structureType ? structureType : StructureTypeEnum.STRUCTURE_TYPE_PRIMITIVE;
                    node = CompilerBuilder.ast(describe);
                    return;
                }
                type = '[' == first ? StructureTypeEnum.STRUCTURE_TYPE_LIST : StructureTypeEnum.STRUCTURE_TYPE_MAP;
                if (StructureTypeEnum.STRUCTURE_TYPE_LIST.equals(type)) {
                    try {
                        list = JsonUtils.json2objWithType(describe, List.class);
                    } catch (JsonProcessingException e) {
                        throw new ConvertException("解析结构出错, 结果描述内容不合法");
                    }
                } else {
                    try {
                        map = JsonUtils.json2objWithType(describe, Map.class);
                    } catch (JsonProcessingException e) {
                        throw new ConvertException("解析结构出错, 结果描述内容不合法");
                    }
                }
            } else if (obj instanceof List) {
                type = StructureTypeEnum.STRUCTURE_TYPE_LIST;
                list = (List<Object>) obj;
            } else if (obj instanceof Map) {
                type = StructureTypeEnum.STRUCTURE_TYPE_MAP;
                map = (Map<String, Object>) obj;
            }
            String prefix = null == name ? "" : name;
            if (null != map) {
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    children.add(new StructureNode(entry.getValue(), prefix + "." + entry.getKey(), prefix));
                }
            } else if (null != list && !list.isEmpty()) {
                analysis(list.get(0), StructureTypeEnum.STRUCTURE_TYPE_LIST);
                //children.add(new StructureNode(list.get(0), prefix + ".[index]", prefix));
            }
            if (null != structureType) {
                type = structureType;
            }
        }
    }
}
